/* 
 * Modbus app for RTU.
 * Copyright (c) 2012  apleilx
 * All rights reserved.
 * no limite
 */

/* ----------------------- Platform includes --------------------------------*/
#define _MAPP_MODULE_
#include "mbapp.h"
#include "os_obj.h"                                          // RTOS object definitions
#include "sys_task.h"
#include "common.h"
#include "app_def.h"

uint8_t mb_inited;

void rcv_end_handle_comp(uint8_t ErrSt);

void mb_smode_callback(uint8_t site, uint8_t err);
void mb_data_update(void);
void mb_config_check(void);
void mb_m_data_handle(void);
void mb_m_cmd_cfg(void);

const mb_parity_type mb_fo_list[] = 
{
    MB_PAR_NONE, 
    MB_PAR_ODD,
    MB_PAR_EVEN,
    MB_PAR_NONE_1S, 
    MB_PAR_NONE, 
    MB_PAR_ODD,
    MB_PAR_EVEN,
    MB_PAR_NONE_1S, 
};

/*****************************************************************************//*!
* @brief   	mb handle.
*               
* @param   none
*
* @return  none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/   
void modbus_task (ULONG thread_input)
{
    mb_config_check();

    mb_poll(&mb_m);

    mb_poll(&mb_pc);
    
    if(mb_m.success_keep_cnt > 1)
    {
        mb_m_data_handle();
    }
}

/*****************************************************************************//*!
* @brief   mb_config_check.
*               
* @param   none
*
* @return  none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/  
void mb_config_check(void)
{
    if(!mb_inited)
    {
        mb_inited = 1;
        
        //从端口初始化
        mb.pc_fo_now = mb.pc_fo_old = mb_pc_cfg.fo;
        mb.pc_baud_now = mb.pc_baud_old = mb_pc_cfg.buad;
        mb.pc_id = mb_pc_cfg.mb_id;
        
        mb_obj_init(&mb_pc);
        mb_pc_init(MB_RTU_SLAVE, mb_pc_cfg.buad, mb_fo_list[mb_pc_cfg.fo]);
        mb_pc.slave_id = mb.pc_id;
        
        // 主端口初始化
        mb.m_fo_now = mb.m_fo_old = mb_m_cfg.fo;
        mb.m_baud_now = mb.m_baud_old = mb_m_cfg.buad;
        mb.m_id = mb_m_cfg.mb_id;
        
        mb_obj_init(&mb_m);
        mb_m_init(MB_RTU_MASTER, mb_m_cfg.buad, mb_fo_list[mb_m_cfg.fo]);
        mb_m.slave_id = mb_m_cfg.mb_id;
        mb_m.rtu_rcv_end_delay_set = 20;
		
		mb_m_cmd_cfg();
    }
    
    //数据格式限定
    if(mb_m_cfg.fo > 3)
        mb_m_cfg.fo = 3;
    if(mb_m_cfg.fo > 3)
        mb_m_cfg.fo = 3;
    
    
    // 从端口设定更新
    mb_pc.slave_id = mb.pc_id;
    mb.pc_fo_now = mb_pc_cfg.fo;
    mb.pc_baud_now = mb_pc_cfg.buad;
    
    if((mb.pc_fo_now != mb.pc_fo_old) || (mb.pc_baud_now != mb.pc_baud_old))
    {
        if(mb_pc.rcv_st != MB_RX_RCV && mb_pc.snd_st != MB_TX_XMIT)
        {
            mb_pc_init(MB_RTU_SLAVE, mb_pc_cfg.buad, mb_fo_list[mb_pc_cfg.fo]);
            
            mb.pc_fo_old = mb.pc_fo_now;
            mb.pc_baud_old = mb.pc_baud_now;  
        }            
    }

    
    // 主端口设定更新
    mb_m.slave_id = mb.m_id;
    mb.m_fo_now = mb_m_cfg.fo;
    mb.m_baud_now = mb_m_cfg.buad;
    
    if((mb.m_fo_now != mb.m_fo_old) || (mb.m_baud_now != mb.m_baud_old))
    {
        if(mb_m.rcv_st != MB_RX_RCV && mb_m.snd_st != MB_TX_XMIT)
        {
            mb_m_init(MB_RTU_SLAVE, mb_m_cfg.buad, mb_fo_list[mb_m_cfg.fo]);
            mb_m.rtu_rcv_end_delay_set = 20;
            
            mb_m_cmd_cfg();
			
            mb.m_fo_old = mb.m_fo_now;
            mb.m_baud_old = mb.m_baud_now;  
        }            
    }
}

/*****************************************************************************//*!
* @brief   mb handle callback.             
* @param   none
* @return  none
* @ Pass/ Fail criteria: none
*****************************************************************************/  
void mb_m_cmd_cfg(void)
{
	mb_cmd_buff_type cmd;
	
		cmd.device_id = mb_m_cfg.mb_id;
		cmd.cmd = FUN_CODE_READ_INPUT;
		cmd.dat = &mb_reg_input[0x00];
		cmd.dat_addr = 0;
		cmd.amount = 16;
		cmd.call_back = 0;

        mmb_stc_cmd_req(&mb_m,0,&cmd);
		
		cmd.dat = &mb_reg_input[0x80];
		cmd.dat_addr = 0x80;
		cmd.amount = 32;
		mmb_stc_cmd_req(&mb_m,1,&cmd);
}


/*****************************************************************************//*!
* @brief   mb handle callback.             
* @param   none
* @return  none
* @ Pass/ Fail criteria: none
*****************************************************************************/  
void mb_m_data_handle(void)
{
    sys_st.rtc_time.year = mb_reg_rtc_year;
    sys_st.rtc_time.mon = mb_reg_rtc_mon;
    sys_st.rtc_time.day = mb_reg_rtc_day;
    sys_st.rtc_time.hour = mb_reg_rtc_hour;
    sys_st.rtc_time.min = mb_reg_rtc_min;
    sys_st.rtc_time.sec = mb_reg_rtc_sec;
}



/*****************************************************************************//*!
* @brief   mb handle callback.             
* @param   none
* @return  none
* @ Pass/ Fail criteria: none
*****************************************************************************/  
void rcv_end_handle_comp(uint8_t ErrSt)
{

}

void mb_smode_callback(uint8_t site, uint8_t err)
{

}
